home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 02 Useful Techniques / 08 Zarozinski / src / ffllapi / COGDefuzzSetObj.cpp next >
Encoding:
C/C++ Source or Header  |  2001-12-01  |  7.1 KB  |  313 lines

  1. //
  2. // File:    COGDefuzzSetObj.h    
  3. //
  4. // Purpose:    Set object for Center of Gravity Defuzzification method
  5. //
  6. // Copyright ⌐ 2001 Louder Than A Bomb! Software
  7. //
  8. // This file is part of the FFLL (Free Fuzzy Logic Library) project (http://ffll.sourceforge.net)
  9. // It is released under the BSD license, see http://ffll.sourceforge.net/license.txt for the full text.
  10. //
  11.  
  12. // include files
  13. #include "COGDefuzzSetObj.h"
  14. #include "FuzzyOutSet.h"
  15. #include "FuzzyOutVariable.h"
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. //
  23. // Function:    COGDefuzzSetObj()
  24. // 
  25. // Purpose:        Constructor
  26. //
  27. // Arguments:
  28. //
  29. //        FuzzyOutSet* par - set that this is part of
  30. //
  31. // Returns:
  32. //
  33. //        none
  34. //
  35. // Author:    Michael Zarozinski
  36. // Date:    6/01
  37. // 
  38. // Modification History
  39. // Author    Date        Modification
  40. // ------    ----        ------------
  41. //
  42. //
  43.  
  44. COGDefuzzSetObj::COGDefuzzSetObj(FuzzyOutSet* par)
  45. : DefuzzSetObj(par), FFLLBase(par)
  46. {
  47.     values = NULL;
  48.  
  49. }; // end COGDefuzzSetObj::COGDefuzzSetObj()
  50.  
  51. //
  52. // Function:    ~COGDefuzzSetObj()
  53. // 
  54. // Purpose:        Destructor
  55. //
  56. // Arguments:
  57. //
  58. //        none
  59. //
  60. // Returns:
  61. //
  62. //        none
  63. //
  64. // Author:    Michael Zarozinski
  65. // Date:    6/01
  66. // 
  67. // Modification History
  68. // Author    Date        Modification
  69. // ------    ----        ------------
  70. //
  71. //
  72.  
  73. COGDefuzzSetObj::~COGDefuzzSetObj()
  74. {
  75.     if (values)
  76.         delete[] values;
  77.  
  78. }; // end COGDefuzzSetObj::~COGDefuzzSetObj()
  79.  
  80. //
  81. // Function:    init()
  82. // 
  83. // Purpose:        Intializes the look up table
  84. //
  85. // Arguments:
  86. //
  87. //        int array_max - how many elements are in the look up table
  88. //
  89. // Returns:
  90. //
  91. //        0 - success
  92. //        non-zero - failure
  93. //
  94. // Author:    Michael Zarozinski
  95. // Date:    6/01
  96. // 
  97. // Modification History
  98. // Author    Date        Modification
  99. // ------    ----        ------------
  100. //
  101. //
  102.  
  103. int COGDefuzzSetObj::init(int array_max)
  104. {
  105.     values = new _cog_struct[array_max];
  106.  
  107.     if (values == NULL)
  108.         {
  109.          set_msg_text(ERR_ALLOC_MEM);
  110.         assert(values != NULL);
  111.         return -1;
  112.         } // end if error allocating memory
  113.  
  114.     return 0;
  115.  
  116. }; // end COGDefuzzSetObj::init()
  117.  
  118.  
  119.  
  120. //
  121. // Function:    calc()
  122. // 
  123. // Purpose:        Calculates the cog under the curve for EVERY Degree of Membership (DOM),
  124. //                creating a lookup table.
  125. //
  126. // Arguments:    
  127. //
  128. //        void
  129. //
  130. // Returns:
  131. //
  132. //        void
  133. //
  134. // Author:    Michael Zarozinski
  135. // Date:    8/01
  136. // 
  137. // Modification History
  138. // Author    Date        Modification
  139. // ------    ----        ------------
  140. //
  141. //
  142.  
  143.  
  144. void COGDefuzzSetObj::calc()
  145. {
  146.     int dom_idx, x_idx;        // counters
  147.     int start_idx, end_idx;    // the indexes that start/end the membership
  148.                             // function in the values array.
  149.     int    y;                    // holds 'y' value for the curve (refered to as DOM
  150.                             // everywhere else but that gets confising here cuz
  151.                             // we're looping through the doms
  152.     RealType area_sum;        // area sum 
  153.     RealType area;            // area 
  154.     RealType moment_sum;    // sum of the moments
  155.  
  156.     // get the min val and idx_multiplier for the var...
  157.  
  158.     FuzzyOutSet* set_base = get_parent();
  159.  
  160.     RealType idx_mult = set_base->get_idx_multiplier();
  161.     RealType min_x = set_base->get_left_x();
  162.  
  163.     start_idx = set_base->get_start_x();
  164.     end_idx = set_base->get_end_x();
  165.  
  166.     // 
  167.     // To calc the COG for each DOM, we treat each index in the values[] 
  168.     // array as a point mass.  Where the mass is equal to the area.
  169.     // Remember Calc 1 where you treated each "segment" of the curve
  170.     // you were integrating as a rectangle?  That's what we're doing here,
  171.     // however when we calculate the HEIGHT of the rectangle we're taking
  172.     // the LESSER of the dom_idx or the value in the values[] array.
  173.     //
  174.     //
  175.     // MAX_DOM                       X
  176.     //                              X X
  177.     //                             X   X
  178.     //                            X     X  
  179.     //                           X       X
  180.     //                          X         X 
  181.     //                         X           X
  182.     //                        X             X
  183.     // dom_idx ----------------------------------------
  184.     //                       XXXXXXXXXXXXXXXXX
  185.     //                      XXXXXXXXXXXXXXXXXXX
  186.     //                     XXXXXXXXXXXXXXXXXXXXX
  187.     // DOM 0              XXXXXXXXXXXXXXXXXXXXXXX
  188.     //                    |                     |
  189.      //                 start_idx            end_idx
  190.     //
  191.  
  192.     // loop through all the doms
  193.     for (dom_idx = 0; dom_idx < FuzzyVariableBase::get_dom_array_count(); dom_idx++)
  194.         {
  195.         // init area and moment for this dom
  196.         area_sum = 0.0;
  197.         moment_sum = 0.0;
  198.  
  199.         // go through the DOMs for the curve 
  200.         for (x_idx = start_idx; x_idx <= end_idx; x_idx++)
  201.             {
  202.             // get the DOM for this 'x' value
  203.             y = set_base->get_dom(x_idx);
  204.  
  205.             // use the LESSER of the 'y' value for this 'x' position or
  206.             // the dom we're checking
  207.  
  208.              if (y > dom_idx)
  209.                  area = dom_idx;
  210.             else
  211.                  area = y;
  212.  
  213.             // add the area to the accumulator
  214.              area_sum += area;
  215.  
  216.             // add the moment to the accumulator
  217.             moment_sum += (RealType)x_idx * area;
  218.  
  219.             } // end loop through curve
  220.  
  221.         set_area(dom_idx, area_sum);
  222.  
  223.         // since the moment invovles the distance from 0 and we use the x_idx
  224.         // above in our calcs, we need to multiply by the index multiplier
  225.         // to convert an index to a 'x' value.  Note: we could have multiplied
  226.         // above when we calculated each moment but it's faster to just perform
  227.         // ONE multiplication here
  228.         // We also add the starting x value of the output variable to get
  229.         // it in the correct position relative to the "origin" of the output variable
  230.  
  231.         set_moment(dom_idx, min_x + (moment_sum * idx_mult ));
  232.  
  233.         } // end loop through DOM
  234.  
  235. } // end COGDefuzzSetObj::calc()
  236.  
  237. //
  238. // Function:    get_defuzz_x()
  239. // 
  240. // Purpose:        This fuction gets the defuzzified 'x' value for a DOM passed in.
  241. //
  242. // Arguments:
  243. //
  244. //        int        dom - 'y' value to get the 'x' value for  
  245. //
  246. // Returns:
  247. //
  248. //        RealType - the defuzzified 'x' value for the set
  249. //
  250. // Author:    Michael Zarozinski
  251. // Date:    12/01
  252. // 
  253. // Modification History
  254. // Author    Date        Modification
  255. // ------    ----        ------------
  256. //
  257. //    
  258. RealType COGDefuzzSetObj::get_defuzz_x(int dom )
  259. {
  260.   
  261.     if (dom < 0)
  262.         {
  263.         return FLT_MIN;
  264.         }
  265.  
  266.     RealType area = get_area(dom); 
  267.  
  268.     if (!area)
  269.         {
  270.         return FLT_MIN;
  271.         }
  272.  
  273.     RealType  moment =  get_moment(dom);  
  274.  
  275.     FuzzyOutSet* set_base = get_parent();
  276.      FuzzyOutVariable* parent = set_base->get_parent();
  277.  
  278.     RealType left_x = parent->get_left_x();
  279.  
  280.     // be sure to account for the left x (start of the var)
  281.     return (left_x + (moment / area));
  282.  
  283.  
  284. } // end COGDefuzzSetObj::get_defuzz_x()
  285.  
  286. /////////////////////////////////////////////////////////////////////
  287. ////////// Trivial Functions That Don't Require Headers /////////////
  288. /////////////////////////////////////////////////////////////////////  
  289.  
  290. RealType COGDefuzzSetObj::get_area(int _idx) const
  291. {
  292.     return values[_idx].area;
  293. };
  294. RealType COGDefuzzSetObj::get_moment(int _idx) const
  295. {
  296.     return values[_idx].moment;
  297. };
  298. void COGDefuzzSetObj::set_area(int _idx, RealType val)
  299. {  
  300.     values[_idx].area = val;
  301. };
  302. void COGDefuzzSetObj::set_moment(int _idx, RealType val)
  303. {  
  304.     values[_idx].moment = val;
  305. };
  306.  
  307. int COGDefuzzSetObj::get_defuzz_type() const
  308.     return DefuzzVarObj::DEFUZZ_TYPE::COG; 
  309. };
  310.  
  311.  
  312.